package org.zlui65.milan

import android.content.Context
import android.content.res.Resources
import android.content.res.TypedArray
import android.util.AttributeSet
import android.view.View
import androidx.annotation.StyleRes

/**
 * Represents a style that can be applied to a view.
 * Styles can be created from XML resources or programmatically.
 */
class Style private constructor(
    private val styleRes: Int? = null,
    private val attributes: MutableMap<Int, Any?> = mutableMapOf()
) {
    companion object {
        /**
         * Creates a style from an XML style resource.
         */
        @JvmStatic
        fun fromStyleResource(@StyleRes styleRes: Int): Style {
            return Style(styleRes = styleRes)
        }

        /**
         * Creates an empty style that can be built programmatically.
         */
        @JvmStatic
        fun create(): Style {
            return Style()
        }
    }

    /**
     * Adds another style to this style.
     * In case of attribute conflicts, the added style's attributes take precedence.
     */
    fun add(other: Style): Style {
        if (other.styleRes != null) {
            // We'll handle the style resource during apply
        }
        attributes.putAll(other.attributes)
        return this
    }

    /**
     * Adds an XML style resource to this style.
     * In case of attribute conflicts, the added style's attributes take precedence.
     */
    fun add(@StyleRes styleRes: Int): Style {
        return add(fromStyleResource(styleRes))
    }

    /**
     * Sets an attribute value.
     */
    fun setAttribute(attrId: Int, value: Any?): Style {
        attributes[attrId] = value
        return this
    }

    /**
     * Applies this style to a view.
     */
    fun applyTo(view: View) {
        // Apply XML style resources first
        styleRes?.let { res ->
            applyXmlStyle(view, res)
        }
        
        // Then apply programmatic attributes
        applyAttributes(view)
    }

    private fun applyXmlStyle(view: View, @StyleRes styleRes: Int) {
        val context = view.context
        val theme = context.theme
        val typedArray = theme.obtainStyledAttributes(styleRes, intArrayOf())
        try {
            StyleApplier.applyStyledAttributes(view, typedArray)
        } finally {
            typedArray.recycle()
        }
    }

    private fun applyAttributes(view: View) {
        StyleApplier.applyAttributes(view, attributes)
    }
}

/**
 * Extension function to apply a style to a view.
 */
fun <T : View> T.style(@StyleRes styleRes: Int): T {
    Style.fromStyleResource(styleRes).applyTo(this)
    return this
}

/**
 * Extension function to apply a style to a view.
 */
fun <T : View> T.style(style: Style): T {
    style.applyTo(this)
    return this
}

/**
 * Extension function to apply a style to a view using a builder.
 */
fun <T : View> T.style(builder: StyleBuilder.() -> Unit): T {
    val styleBuilder = StyleBuilder()
    styleBuilder.builder()
    styleBuilder.build().applyTo(this)
    return this
}

/**
 * Extension function to apply an AttributeSet to a view.
 */
fun <T : View> T.style(attrs: AttributeSet?): T {
    if (attrs != null) {
        StyleApplier.applyAttributeSet(this, attrs)
    }
    return this
}

/**
 * Builder for creating styles programmatically.
 */
class StyleBuilder {
    private val style = Style.create()

    /**
     * Adds an XML style resource to this style.
     */
    fun add(@StyleRes styleRes: Int) {
        style.add(styleRes)
    }

    /**
     * Adds another style to this style.
     */
    fun add(other: Style) {
        style.add(other)
    }

    /**
     * Sets an attribute value.
     */
    fun setAttribute(attrId: Int, value: Any?) {
        style.setAttribute(attrId, value)
    }

    /**
     * Builds the style.
     */
    fun build(): Style {
        return style
    }
}
